package org.madmac.placaRede;

import org.madmac.ip.IpDao;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;

import org.madmac.exception.PlacaDeRedeNotFoundException;
import org.wakeful.conn.Connection;
import org.wakeful.query.Query;
import org.wakeful.sql.PStatementParam;

public class PlacaRedeDao {

   private static PlacaRedeDao instance;

   private PlacaRedeDao() {
   }

   public static PlacaRedeDao getInstance() {
      if (instance == null) {
         instance = new PlacaRedeDao();
      }
      return instance;
   }

   public void create(PlacaRede placa) throws Exception {
      PreparedStatement pstmt = null;
      try {
         /* escolhe um ip livre a partir da faixa */
         String ipLivre = IpDao.getInstance().selectIpLivre(placa.getIp().getFaixaIp().getIdFaixa());

         java.sql.Connection conn = Connection.getInstance();
         pstmt = conn.prepareStatement(PlacaRedeQuery.create());
         pstmt.setObject(1, placa.getMac(), Types.OTHER);
         pstmt.setBoolean(2, placa.isRedeSemFio());
         pstmt.setInt(3, placa.getMaquina().getIdMaquina());
         pstmt.setObject(4, ipLivre, Types.OTHER);
         pstmt.executeUpdate();
      } catch (Exception e) {
         throw new Exception(e);
      } finally {
         if (pstmt != null) {
            pstmt.close();
         }
      }
   }

   public void update(PlacaRede placa) throws Exception {
      PreparedStatement pstmt = null;
      try {
         // TODO: verificar se é a mesma faixa ip e não mudar o ip.
         String ipLivre = IpDao.getInstance().selectIpLivre(placa.getIp().getFaixaIp().getIdFaixa());

         java.sql.Connection conn = Connection.getInstance();
         pstmt = conn.prepareStatement(PlacaRedeQuery.update());
         pstmt.setInt(1, placa.getMaquina().getIdMaquina());
         pstmt.setObject(2, ipLivre, Types.OTHER);
         pstmt.setBoolean(3, placa.isRedeSemFio());
         pstmt.setObject(4, placa.getMac(), Types.OTHER);
         pstmt.executeUpdate();
      } catch (Exception e) {
         throw new Exception(e);
      } finally {
         if (pstmt != null) {
            pstmt.close();
         }
      }
   }

   public PlacaRede findByMac(String mac) throws Exception {

		PreparedStatement pstmt = null;
      ResultSet rs = null;
      PlacaRede placa = null;
      try {
         java.sql.Connection conn = Connection.getInstance();
         pstmt = conn.prepareStatement(PlacaRedeQuery.findByMac());
         pstmt.setObject(1, mac, Types.OTHER);
         rs = pstmt.executeQuery();
         if (rs.next()) {
            placa = new PlacaRede();

            placa.setMac(rs.getString("mac"));
            placa.setRedeSemFio(rs.getBoolean("acesso_sem_fio"));
            placa.getIp().setIp(rs.getString("ip"));
            placa.getMaquina().getSetor().setNome(rs.getString("setor"));
            placa.getMaquina().getPessoa().setNome(rs.getString("responsavel"));
            placa.getMaquina().setSistemaOp(rs.getString("sistema_op"));
            placa.getMaquina().setTombamento(rs.getInt("tombamento"));
            placa.getIp().getFaixaIp().setDescricao(rs.getString("faixa"));
            placa.getIp().getFaixaIp().setIdFaixa(rs.getInt("id_faixa_ip"));
         }
      } catch (Exception e) {
         throw new Exception(e);
      } finally {
         if (pstmt != null) {
            pstmt.close();
         }
         if (rs != null) {
            rs.close();
         }
      }
      return placa;
   }

	public List<PlacaRede> findAll(Integer idSetor, Integer idFaixaIp) throws Exception {
		
		List<PlacaRede> list = new ArrayList<PlacaRede>();
		PreparedStatement pstmt = null;
      ResultSet rs = null;
		try {
			java.sql.Connection conn = Connection.getInstance();
			StringBuilder builder = new StringBuilder();
         builder.append(PlacaRedeQuery.findAll());
         
         // DONE: usar parametros dinamicos para a query.
         List<PStatementParam> param = new ArrayList<PStatementParam>();
         boolean incluir = false;
         builder.append(Query.WHERE);
         if (idSetor != null) {
            builder.append("s.id_setor = ?");
            param.add(new PStatementParam(idSetor, Types.INTEGER));
            incluir = true;
         }

         if (idFaixaIp != null) {
            if (incluir) {
               builder.append(Query.AND);
            }
            builder.append("f.id_faixa_ip = ?");
            param.add(new PStatementParam(idFaixaIp, Types.INTEGER));
         }
			
         pstmt = conn.prepareStatement(builder.toString());
         for (int i = 0; i < param.size(); i++) {
            pstmt.setObject( (i + 1), param.get(i).getObj(), param.get(i).getTypes() );
         }
         rs = pstmt.executeQuery();

         while (rs.next()) {
            PlacaRede placa = new PlacaRede();

            placa.setMac(rs.getString("mac"));
            placa.setRedeSemFio(rs.getBoolean("acesso_sem_fio"));
            placa.getIp().setIp(rs.getString("ip"));
            placa.getMaquina().getSetor().setNome(rs.getString("setor"));
            placa.getMaquina().getPessoa().setNome(rs.getString("responsavel"));
            placa.getMaquina().setSistemaOp(rs.getString("sistema_op"));
            placa.getMaquina().setTombamento(rs.getInt("tombamento"));
            placa.getIp().getFaixaIp().setDescricao(rs.getString("faixa"));
            placa.getIp().getFaixaIp().setIdFaixa(rs.getInt("id_faixa_ip"));

            list.add(placa);
         }
		} catch (Exception e) {
         System.out.println("Erro: " + e.getMessage());
         throw new Exception(e);
      } finally {
         if (pstmt != null) {
            pstmt.close();
         }
         if (rs != null) {
            rs.close();
         }
		}
		return list;
	}

   /**
    *
    * @return
    * @throws SQLException
    * @throws ClassNotFoundException
    * @throws Exception
    * @deprecated 
    */
   public List<PlacaRede> selectAll() throws SQLException, ClassNotFoundException, Exception {

      List<PlacaRede> lista = new ArrayList<PlacaRede>();

      java.sql.Connection conn = Connection.getInstance();
      Statement stmt = conn.createStatement();
      String sql = "SELECT * FROM madmac.placa_rede ";

      ResultSet rs = null;
      try {
         rs = stmt.executeQuery(sql);
      } catch (Exception e) {
         return null;
      }

      while (rs.next()) {
         String mac = rs.getString("mac");
         int id_maquina = rs.getInt("id_maquina");
         String ip = rs.getString("ip");
         boolean rede_sem_fio = rs.getBoolean("rede_sem_fio");

         PlacaRede placa = new PlacaRede();
         placa.setMac(mac);
         placa.getMaquina().setIdMaquina(id_maquina);
         //placa.setIp(ip);
         placa.setRedeSemFio(rede_sem_fio);

         lista.add(placa);
      }
      return lista;
   }

   public PlacaRede selectByMAC(String search_mac) throws SQLException, ClassNotFoundException, Exception {

      PlacaRede placa = null;
      java.sql.Connection conn = Connection.getInstance();
      Statement stmt = conn.createStatement();
      String sql = "SELECT * FROM madmac.placa_rede WHERE mac = " + search_mac + " ";

      ResultSet rs = null;
      try {
         rs = stmt.executeQuery(sql);
      } catch (Exception e) {
         return null;
      }

      if (rs.next()) {

         placa = new PlacaRede();
         String mac = rs.getString("mac");
         int id_maquina = rs.getInt("id_maquina");
         String ip = rs.getString("ip");
         boolean rede_sem_fio = rs.getBoolean("rede_sem_fio");

         placa.setMac(mac);
         placa.getMaquina().setIdMaquina(id_maquina);
         //placa.setIp(ip);
         placa.setRedeSemFio(rede_sem_fio);

      } else {
         throw new PlacaDeRedeNotFoundException();
      }
      return placa;
   }

   /**
    *
    * @param placa
    * @return
    * @throws SQLException
    * @throws ClassNotFoundException
    * @throws Exception
    * @deprecated
    */
   public boolean insertPlacaDeRede(PlacaRede placa) throws SQLException, ClassNotFoundException, Exception {

      java.sql.Connection conn = Connection.getInstance();
      PreparedStatement pstmt = null;
      try {
         /* escolhe um ip livre a partir da faixa */
         String ipLivre = IpDao.getInstance().selectIpLivre(placa.getIp().getFaixaIp().getIdFaixa());

         //String sql = "INSERT INTO madmac.placa_rede (mac, acesso_sem_fio, id_maquina, ip) VALUES (?, ?, ?, ?)";
         pstmt = conn.prepareStatement(PlacaRedeQuery.create());
         pstmt.setObject(1, placa.getMac(), Types.OTHER);
         pstmt.setBoolean(2, placa.isRedeSemFio());
         pstmt.setInt(3, placa.getMaquina().getIdMaquina());
         pstmt.setObject(4, ipLivre, Types.OTHER);
         return pstmt.execute();
      } catch (Exception e) {
         throw new Exception(e);
      } finally {
         if (pstmt != null) {
            pstmt.close();
         }
      }
   }

   public boolean deletePlacaDeRede(String del_mac) throws SQLException, ClassNotFoundException, Exception {

      java.sql.Connection conn = Connection.getInstance();
      Statement stmt = conn.createStatement();
      String sql = "DELETE FROM madmac.placa_rede WHERE mac = '" + del_mac.toLowerCase() + "' ";
      int count = stmt.executeUpdate(sql);

      boolean resultado = false;

      if (count == 1) {

         resultado = true;
      }

      return resultado;
   }

   /**
    *
    * @param placa
    * @param macAddress
    * @return
    * @throws SQLException
    * @throws ClassNotFoundException
    * @throws Exception
    * @deprecated
    */
   public boolean updatePlacaDeRede(PlacaRede placa, String macAddress) throws SQLException, ClassNotFoundException, Exception {

      java.sql.Connection conn = Connection.getInstance();
      PreparedStatement pstmt = null;
      try {
         String ipLivre = IpDao.getInstance().selectIpLivre(placa.getIp().getFaixaIp().getIdFaixa());

         pstmt = conn.prepareStatement(PlacaRedeQuery.update());
         pstmt.setInt(1, placa.getMaquina().getIdMaquina());
         pstmt.setObject(2, ipLivre, Types.OTHER);
         pstmt.setBoolean(3, placa.isRedeSemFio());
         pstmt.setObject(4, placa.getMac(), Types.OTHER);
         return pstmt.execute();
      } catch (Exception e) {
         throw new Exception(e);
      } finally {
         if (pstmt != null) {
            pstmt.close();
         }
      }
   }
}
